package com.yikome.delivery.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.web.PageableDefault;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.common.base.Preconditions;
import com.itmuch.lightsecurity.annotation.PreAuthorize;
import com.yikome.constant.CommonConstant;
import com.yikome.delivery.dto.DeliveryDetailsSearchDTO;
import com.yikome.delivery.dto.DeliveryExportDTO;
import com.yikome.delivery.dto.DeliveryExportRowDTO;
import com.yikome.delivery.dto.DeliverySearchDTO;
import com.yikome.delivery.dto.OrderDeliverySearchDTO;
import com.yikome.delivery.request.DeliverySearchRequest;
import com.yikome.delivery.request.DeliverySendOutRequest;
import com.yikome.delivery.service.DeliveryService;
import com.yikome.tracker.htc.HCTLogisticsResponse;
import com.yikome.utils.BeanUtils;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
@RequestMapping("/admin/delivery")
public class DeliveryController {

	@Autowired
	private DeliveryService deliveryService ; 
	
	@GetMapping("/{orderCode}/tracking")
	public List<HCTLogisticsResponse> findOrderDeliveryTrack(@PathVariable("orderCode")String orderCode) {
		
		return deliveryService.findOrderDeliveryTrack(orderCode);
	}
	
	@GetMapping("/list")
	@PreAuthorize("hasAnyRoles('admin','analysis', 'storehouse', 'finance', 'order')")
	public Page<DeliverySearchDTO> findDeliverySearchDTO(DeliverySearchRequest deliverySearchRequest , @PageableDefault(direction = Direction.DESC , sort = {"d_delivery.id"}) Pageable pageable){
		
		return deliveryService.findDeliverySearchDTO(deliverySearchRequest , pageable);
	}
	
	@GetMapping("/{orderCode}/deliveries")
	public List<OrderDeliverySearchDTO> findOrderDeliveries(@PathVariable("orderCode") String orderCode) {
		
		return deliveryService.findOrderDeliveries(orderCode);
	}
	
	
	@GetMapping("/{deliveryCode}/details")
	@PreAuthorize("hasAnyRoles('admin','analysis', 'storehouse', 'finance', 'order')")
	public List<DeliveryDetailsSearchDTO> findDeliveryDetails(@PathVariable("deliveryCode") String deliveryCode){
		
		return deliveryService.findDeliveryDetails(deliveryCode);
	}
	
	@GetMapping("/list/export")
	@PreAuthorize("hasAnyRoles('admin','analysis', 'storehouse', 'finance', 'order')")
	public String findDeliveryExportDTO(DeliverySearchRequest deliverySearchRequest , @PageableDefault(direction = Direction.DESC , sort = {"d_delivery.id" , "d_delivery_details.product_sku_barcode"}) Pageable pageable) throws Exception{
		
		List<DeliveryExportDTO> deliveryExportDTOs = deliveryService.findDeliveryExportDTO(deliverySearchRequest , PageRequest.of(0, 100000, Direction.DESC, "d_delivery.id" , "d_delivery_details.product_sku_barcode"));
	
		Map<String, DeliverySearchDTO> oMap = new HashMap<>();
		for (DeliveryExportDTO deliveryExportDTO : deliveryExportDTOs) {
			
			DeliveryDetailsSearchDTO deliveryDetailsSearchDTO = new DeliveryDetailsSearchDTO();
			BeanUtils.copyProperties(deliveryExportDTO, deliveryDetailsSearchDTO);
			
			if(oMap.containsKey(deliveryExportDTO.getDeliveryCode())) {
				oMap.get(deliveryExportDTO.getDeliveryCode()).getDeliveryDetailsSearchDTOs().add(deliveryDetailsSearchDTO);
			}else {
				
				DeliverySearchDTO deliverySearchDTO = new DeliverySearchDTO();
				BeanUtils.copyProperties(deliveryExportDTO, deliverySearchDTO);
				deliverySearchDTO.setDetail(StrUtil.join(" ", deliveryExportDTO.getCity(), deliveryExportDTO.getDistrict(), deliveryExportDTO.getDetail()));
				
				deliverySearchDTO.setDeliveryDetailsSearchDTOs(new ArrayList<>());
				
				deliverySearchDTO.getDeliveryDetailsSearchDTOs().add(deliveryDetailsSearchDTO);
				
				oMap.put(deliveryExportDTO.getDeliveryCode(), deliverySearchDTO);
			}
		}
		Collection<DeliverySearchDTO> deliverySearchDTOs = oMap.values();
		
		Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("发货单信息", "发货单信息"), DeliverySearchDTO.class, deliverySearchDTOs);
		
		String folderPath = CommonConstant.BASE_LOCATION + LocalDateTime.now(ZoneId.of("+8")).format(CommonConstant.DATETIMEFORMATTRT_DATE) + '/' ;
		File fileFolder = new File(folderPath);
		if (!fileFolder.exists())fileFolder.mkdirs();
		
		String fileName = LocalDateTime.now(ZoneId.of("+8")).format(CommonConstant.DATETIMEFORMATTRT_TIME) + "-发货单.xlsx" ;
		
		String filePath = folderPath + fileName ;
		FileOutputStream fos = new FileOutputStream(filePath);
		workbook.write(fos);
        fos.close();
		return filePath ; 
	}
	
	@GetMapping("/list/exportRow")
	@PreAuthorize("hasAnyRoles('admin','analysis', 'storehouse', 'finance', 'order')")
	public String findDeliveryExportDTORow(DeliverySearchRequest deliverySearchRequest , @PageableDefault(direction = Direction.DESC , sort = {"d_delivery.id" , "d_delivery_details.product_sku_barcode"}) Pageable pageable) throws Exception{
		
		List<DeliveryExportDTO> deliveryExportDTOs = deliveryService.findDeliveryExportDTO(deliverySearchRequest , PageRequest.of(0, 100000, Direction.DESC, "d_delivery.id" , "d_delivery_details.product_sku_barcode"));
	
		Map<String, DeliverySearchDTO> oMap = new HashMap<>();
		for (DeliveryExportDTO deliveryExportDTO : deliveryExportDTOs) {
			
			DeliveryDetailsSearchDTO deliveryDetailsSearchDTO = new DeliveryDetailsSearchDTO();
			BeanUtils.copyProperties(deliveryExportDTO, deliveryDetailsSearchDTO);
			
			if(oMap.containsKey(deliveryExportDTO.getDeliveryCode())) {
				oMap.get(deliveryExportDTO.getDeliveryCode()).getDeliveryDetailsSearchDTOs().add(deliveryDetailsSearchDTO);
			}else {
				
				DeliverySearchDTO deliverySearchDTO = new DeliverySearchDTO();
				BeanUtils.copyProperties(deliveryExportDTO, deliverySearchDTO);
				deliverySearchDTO.setDeliveryDetailsSearchDTOs(new ArrayList<>());
				
				deliverySearchDTO.getDeliveryDetailsSearchDTOs().add(deliveryDetailsSearchDTO);
				
				oMap.put(deliveryExportDTO.getDeliveryCode(), deliverySearchDTO);
			}
		}
		Collection<DeliverySearchDTO> deliverySearchDTOs = oMap.values();
		
		
		//将一对多整理成一对一的关系
		List<DeliveryExportRowDTO> deliveryExportRowDTOs = new ArrayList<>();
		for (DeliverySearchDTO deliverySearchDTO : deliverySearchDTOs) {
			DeliveryExportRowDTO tmp = new DeliveryExportRowDTO();
			BeanUtils.copyProperties(deliverySearchDTO, tmp);
			tmp.setQuantities(0);
			
			StringBuilder productTitles = new StringBuilder("");
			StringBuilder productSkuBarcodes = new StringBuilder("");
			StringBuilder productSkuNames = new StringBuilder("");
			
			List<DeliveryDetailsSearchDTO> searchDTOs = deliverySearchDTO.getDeliveryDetailsSearchDTOs();
			for (DeliveryDetailsSearchDTO dto : searchDTOs) {
				productTitles.append(";").append(dto.getProductTitle()).append("*").append(dto.getQuantity());
				productSkuBarcodes.append(";").append(dto.getProductSkuBarcode()).append("*").append(dto.getQuantity());
				productSkuNames.append(";").append(dto.getProductSkuName()).append("*").append(dto.getQuantity());
				tmp.setQuantities(tmp.getQuantities() + dto.getQuantity());
			}
			
			tmp.setDetail(StrUtil.join(" ", deliverySearchDTO.getCity(), deliverySearchDTO.getDistrict(), deliverySearchDTO.getDetail()));
			tmp.setProductTitles(productTitles.length() > 0 ? productTitles.substring(1) : "");
			tmp.setProductSkuBarcodes(productSkuBarcodes.length() > 0 ? productSkuBarcodes.substring(1) : "");
			tmp.setProductSkuNames(productSkuNames.length() > 0 ? productSkuNames.substring(1) : "");
			
			deliveryExportRowDTOs.add(tmp);
		}
		Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("发货单信息", "发货单信息"), DeliveryExportRowDTO.class, deliveryExportRowDTOs);
		
		String folderPath = CommonConstant.BASE_LOCATION + LocalDateTime.now(ZoneId.of("+8")).format(CommonConstant.DATETIMEFORMATTRT_DATE) + '/' ;
		File fileFolder = new File(folderPath);
		if (!fileFolder.exists())fileFolder.mkdirs();
		
		String fileName = LocalDateTime.now(ZoneId.of("+8")).format(CommonConstant.DATETIMEFORMATTRT_TIME) + "-发货单.xlsx" ;
		
		String filePath = folderPath + fileName ;
		FileOutputStream fos = new FileOutputStream(filePath);
		workbook.write(fos);
        fos.close();
		return filePath ; 
	}
	
	@PutMapping("/generate")
	@PreAuthorize("hasAnyRoles('admin', 'storehouse', 'order')")
	public Boolean generateDelivery() {
		
		deliveryService.generateDelivery();
		
		return Boolean.TRUE;
	}
	
	
	@PutMapping("/send")
	@PreAuthorize("hasAnyRoles('admin','storehouse' ,'order')")
	public List<DeliverySendOutRequest> deliverySendOut(@RequestBody List<DeliverySendOutRequest> deliverySendOutRequests) {
		
		List<DeliverySendOutRequest> errors = new ArrayList<>();
		
		for (DeliverySendOutRequest deliverySendOutRequest : deliverySendOutRequests) {
			
			try {
				Preconditions.checkArgument(StrUtil.isNotBlank(deliverySendOutRequest.getDeliveryCode()), "发货单号不存在...");
				Preconditions.checkArgument(StrUtil.isNotBlank(deliverySendOutRequest.getLogisticsCode()), "发货单号不存在...");
				Preconditions.checkArgument(StrUtil.isNotBlank(deliverySendOutRequest.getLogisticsCompany()), "物流公司不存在...");
				deliveryService.deliverySendOut(deliverySendOutRequest);
			}catch (Exception e) {
				deliverySendOutRequest.setErrorMsg(e.getMessage());
				errors.add(deliverySendOutRequest);
			}
		}
		return errors ; 
	}
	
	@PostMapping("/remote/packed")
	public Boolean remoteDeliverySendOut(@RequestBody DeliverySendOutRequest deliverySendOutRequest, HttpServletRequest request) {
		
		String salt = request.getParameter("salt") ; 
		Preconditions.checkArgument(StrUtil.isNotBlank(salt), "认证标识不存在...");
		
		String md5 = SecureUtil.md5(SecureUtil.md5("packed"));
		Preconditions.checkArgument(StrUtil.equalsIgnoreCase(salt, md5), "访问标识salt不正确...");
		
		Preconditions.checkArgument(StrUtil.isNotBlank(deliverySendOutRequest.getDeliveryCode()), "发货单号不存在...");
		Preconditions.checkArgument(StrUtil.isNotBlank(deliverySendOutRequest.getLogisticsCode()), "发货单号不存在...");
		Preconditions.checkArgument(StrUtil.isNotBlank(deliverySendOutRequest.getLogisticsCompany()), "物流公司不存在...");
		deliveryService.deliverySendOut(deliverySendOutRequest);
		
		return Boolean.TRUE ; 
	}
	
	//TODO
	public static void main(String[] args) {
		System.out.println(SecureUtil.md5(SecureUtil.md5("packed")));
	}
	
	@DeleteMapping("/{deliveryCode}")
	@PreAuthorize("hasAnyRoles('admin', 'order')")
	public Boolean deliveryDelete(@PathVariable("deliveryCode") String deliveryCode) {
		
		deliveryService.deleteDelivery(deliveryCode);
		
		return Boolean.TRUE ; 
	}
}
